package com.example.onlinemonitoring.comCenter;

import com.example.onlinemonitoring.Util.CRC16;
import com.example.onlinemonitoring.Util.CommPortManager;
import com.example.onlinemonitoring.Util.HexUtil;
import com.example.onlinemonitoring.model.Wjbhsensor;
import com.example.onlinemonitoring.model.Wjbhhistory;
import com.example.onlinemonitoring.model.Appdevice;
import org.springframework.context.annotation.Scope;
import com.example.onlinemonitoring.serviceImpl.WjbhsensorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 微机保护
 */
/*
 * 这里beanName需要和数据库Appdevice中的simple对应并加上Com,不对应请自行修改
 * 例:simple:dlhl
 * 
 * @Service("dlhlCom")
 */
@Service("wjbhCom")
@Scope("prototype")
public class WjbhCom extends CommPortManager {
    @Autowired
    private WjbhsensorServiceImpl wjbhsensorServiceImpl;

    @Override
    public void receiveDatas(String str) {
        try {
            str = str.toUpperCase();
            setText(str);
            // 条件判断自己写
            // 01030300BF00DF00E19AEC
            // 获取地址
            int addr = parseHex4(str.substring(0, 2));
            reSend[addr] = 0;
            if (currcmd == 1) {
                addrindex++;
            }
            setText("设备返回数据： 站点号：" + ad.getStationid() + " 设备组：" + ad.getDevicegroup() + " 设备地址：" + addr);
            // 获取功能码
            switch (str.substring(2, 4)) {
                case "04": {
                    Wjbhsensor wjbh = new Wjbhsensor();
                    wjbh.setStationid(ad.getStationid());
                    wjbh.setDevicegroup(ad.getDevicegroup());
                    wjbh.setDeviceaddr(addr);
                    wjbh = wjbhsensorServiceImpl.getModel(wjbh);
                    if (wjbh == null) {
                        setText("当前数据库无设备：设备地址" + addr + "请先添加设备！");
                        return;
                    } else {
                        int start_index = 6;
                        // IA
                        String acurrnet_str = str.substring(start_index, start_index += 8);
                        // IB
                        String bcurrnet_str = str.substring(start_index, start_index += 8);
                        // IC
                        String ccurrnet_str = str.substring(start_index, start_index += 8);
                        float acurrent = Float.isNaN(Integer.parseInt(acurrnet_str, 16) / 100f) ? 0f
                                : Integer.parseInt(acurrnet_str, 16) / 100f;
                        float bcurrent = Float.isNaN(Integer.parseInt(bcurrnet_str, 16) / 100f) ? 0f
                                : Integer.parseInt(bcurrnet_str, 16) / 100f;
                        float ccurrent = Float.isNaN(Integer.parseInt(ccurrnet_str, 16) / 100f) ? 0f
                                : Integer.parseInt(ccurrnet_str, 16) / 100f;
                        setText("A相电流：" + acurrent + "A" + " B相电流：" + bcurrent + "A" + " C相电流：" + ccurrent + "A");
                        wjbh.setLastacurrent(acurrent);
                        wjbh.setLastbcurrent(bcurrent);
                        wjbh.setLastccurrent(ccurrent);
                        AddAndUpdate(wjbh);
                    }
                }
                    break;
                case "02": {
                    byte[] carr = HexUtil.hexString2Bytes(str);
                    int closing = carr[3] >> 0 & 1;
                    int opening = carr[3] >> 1 & 1;
                    int workpos = carr[3] >> 2 & 1;
                    int testpos = carr[3] >> 3 & 1;
                    Wjbhsensor wjbh = new Wjbhsensor();
                    wjbh.setStationid(ad.getStationid());
                    wjbh.setDevicegroup(ad.getDevicegroup());
                    wjbh.setDeviceaddr(addr);
                    wjbh.setLastclosing(closing);
                    wjbh.setLastopening(opening);
                    wjbh.setLastworkpos(workpos);
                    wjbh.setLasttestpos(testpos);
                    setText("合位：" + closing + " 分位：" + opening + " 工作位：" + workpos + " 试验位：" + testpos);
                    if (wjbhsensorServiceImpl.Update(wjbh, false) == 0) {
                        setText("更新实时数据失败，请检查数据库连接");
                    }
                }
                    break;
                default:
                    break;
            }

        } catch (Exception ex) {
            ex.printStackTrace();
            setText("从设备返回的数据有误！请检查串口！");
        }
    }

    @Transactional
    private void AddAndUpdate(Wjbhsensor record) {
        String alarmMessage = "";// 报警消息
        // 判断是否设置了报警值
        if (record.getAcurrnetalarmvalue() == null || record.getAcurrnetalarmrelievevalue() == null
                || record.getAcurrentwarnvalue() == null
                || record.getAcurrentwarnrelievevalue() == null ||
                record.getBcurrnetalarmvalue() == null || record.getBcurrnetalarmrelievevalue() == null
                || record.getBcurrentwarnvalue() == null
                || record.getBcurrentwarnrelievevalue() == null ||
                record.getCcurrnetalarmvalue() == null || record.getCcurrnetalarmrelievevalue() == null
                || record.getCcurrentwarnvalue() == null
                || record.getCcurrentwarnrelievevalue() == null) {
            setText("设备地址" + record.getDeviceaddr() + " 未设置报警值！");
            return;
        }
        // 打印获得的传感器数据
        // 报警逻辑
        record.setLastaalarmstatus(GetAlarmStatus(HexUtil.isnull(record.getLastacurrent()),
                HexUtil.isnull(record.getAcurrnetalarmvalue()),
                HexUtil.isnull(record.getAcurrnetalarmrelievevalue()), HexUtil.isnull(record.getAcurrentwarnvalue()),
                HexUtil.isnull(record.getAcurrentwarnrelievevalue()),
                HexUtil.isnull(record.getLastaalarmstatus()), true, "A相电流",record.getDevicegroup(), record.getDeviceaddr(),
                record.getPointname()));
        record.setLastbalarmstatus(GetAlarmStatus(HexUtil.isnull(record.getLastbcurrent()),
                HexUtil.isnull(record.getBcurrnetalarmvalue()),
                HexUtil.isnull(record.getBcurrnetalarmrelievevalue()), HexUtil.isnull(record.getBcurrentwarnvalue()),
                HexUtil.isnull(record.getBcurrentwarnrelievevalue()),
                HexUtil.isnull(record.getLastbalarmstatus()), true, "B相电流",record.getDevicegroup(), record.getDeviceaddr(),
                record.getPointname()));
        record.setLastcalarmstatus(GetAlarmStatus(HexUtil.isnull(record.getLastccurrent()),
                HexUtil.isnull(record.getCcurrnetalarmvalue()),
                HexUtil.isnull(record.getCcurrnetalarmrelievevalue()), HexUtil.isnull(record.getCcurrentwarnvalue()),
                HexUtil.isnull(record.getCcurrentwarnrelievevalue()),
                HexUtil.isnull(record.getLastcalarmstatus()), true, "C相电流",record.getDevicegroup(), record.getDeviceaddr(),
                record.getPointname()));
        record.setLastalarmlevel(Math.max(Math.max(record.getLastaalarmstatus(), record.getLastbalarmstatus()),
                record.getLastcalarmstatus()));
        record.setLastalarmmessage(GetAlarmMessage(record.getLastaalarmstatus(), "A相电流") +
                GetAlarmMessage(record.getLastbalarmstatus(), "B相电流") +
                GetAlarmMessage(record.getLastcalarmstatus(), "C相电流"));
        record.setLastcommunicationstatus(0);
        record.setLastdatatime(new Date());
        Wjbhsensor wjbh = new Wjbhsensor();
        wjbh.setStationid(ad.getStationid());
        wjbh.setDevicegroup(ad.getDevicegroup());
        wjbh.setDeviceaddr(record.getDeviceaddr());
        record.setLasthisdatatime(addHistory(wjbhsensorServiceImpl.getModel(wjbh)));
        if (wjbhsensorServiceImpl.Update(record, false) == 0) {
            setText("更新实时数据失败，请检查数据库连接");
        }
    }

    private Date addHistory(Wjbhsensor sensor) {
        if (sensor != null) {
            if (sensor.getLasthisdatatime() == null) {
                add(sensor);
                return new Date();
            } else {
                long lasttime = 0;
                long nowtime = 0;
                try {
                    lasttime = HexUtil.todate(sensor.getLasthisdatatime()).getTime();
                    nowtime = HexUtil.todate(new Date()).getTime();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                int timersp = 60000;
                if (sensor.getLastalarmlevel() != 0) {
                    timersp = ad.getHisalarmtimersp() * 1000;
                } else {
                    timersp = ad.getHistimersp() * 1000;
                }
                if (lasttime + timersp < nowtime) {
                    add(sensor);
                    return new Date();
                }
            }
        }
        return null;
    }

    private void add(Wjbhsensor sensor) {
        Wjbhhistory his = new Wjbhhistory();
        his.setDeviceaddr(sensor.getDeviceaddr());
        his.setDevicegroup(sensor.getDevicegroup());
        his.setAlarmlevel(sensor.getLastalarmlevel());
        his.setAlarmmessage(sensor.getLastalarmmessage());
        his.setDatatime(sensor.getLastdatatime());
        his.setPointname(sensor.getPointname());
        his.setStationid(sensor.getStationid());
        his.setCommunicationstatus(sensor.getLastcommunicationstatus());
        // 需要添加自己定义的属性
        his.setAcurrent(sensor.getLastacurrent());
        his.setBcurrent(sensor.getLastbcurrent());
        his.setCcurrent(sensor.getLastccurrent());
        his.setAalarmstatus(sensor.getLastaalarmstatus());
        his.setBalarmstatus(sensor.getLastbalarmstatus());
        his.setCalarmstatus(sensor.getLastcalarmstatus());
        his.setOpening(sensor.getLastopening());
        his.setClosing(sensor.getLastclosing());
        his.setWorkpos(sensor.getLastworkpos());
        his.setTestpos(sensor.getLasttestpos());
        wjbhsensorServiceImpl.Add(his);
    }

    @Async("threadPool")
    public void startSendThread(Appdevice Appdevice) throws Exception {
        checkType = "crc16";
        issend.put(Thread.currentThread().getId(), true);
        String cstr = "";
        String cmd[] = new String[3];
        cmd[0] = "%s0208000004";// 遥信
        cmd[1] = "%s0406060006";// 遥测
        int timeoutsp = (int) Math.round(Appdevice.getTimeoutsp() * 1000);
        timersp = (int) Math.round(Appdevice.getTimersp() * 1000);
        while (issend.get(Thread.currentThread().getId()) != null) {
            rlock.lock();
            try {
                if (isrun) {
                    if (addrindex > Appdevice.getAddrmax() || addrindex < Appdevice.getAddrmin())
                        addrindex = Appdevice.getAddrmin();
                    cstr = String.format(cmd[currcmd], String.format("%02X", addrindex));
                    cstr = cstr + CRC16.calcCrc16(cstr);
                    Send(cstr);
                    sendCondition.await(timeoutsp, TimeUnit.MILLISECONDS);
                    currcmd++;

                    cstr = String.format(cmd[currcmd], String.format("%02X", addrindex));
                    cstr = cstr + CRC16.calcCrc16(cstr);
                    Send(cstr);
                    sendCondition.await(timeoutsp, TimeUnit.MILLISECONDS);
                    currcmd = 0;
                    if (reSend[addrindex] > 3) {
                        wjbhsensorServiceImpl.UpdateStatus(ad, addrindex, 1);
                        reSend[addrindex] = 0;
                        addrindex++;
                    }
                    reSend[addrindex]++;
                } else if (rescode != 0) {
                    setText(resmsg[rescode]);
                }
            } catch (Exception e) {
                // TODO: handle exception
            } finally {
                rlock.unlock();
            }
        }
    }
}
